const targetMap = new WeakMap();
const effectStack = [];

const isObject = value => {
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}

const reactive = obj => {
  if(!isObject(obj)) return obj;
  const get = (target, key) => {
    track(target, key);
    const res = Reflect.get(target, key);
    return reactive(res);
  }
  const set = (target, key, value) => {
    trigger(target, key);
    return Reflect.set(target, key, value);
  }
  return new Proxy(obj, {
    get,
    set,
  })
}

// 收集依赖
const track = (target, key) => {
  const activeEffect = effectStack[effectStack.length - 1];
  if(!activeEffect) return;
  let depsMap = targetMap.get(target);
  if(!depsMap) {
    targetMap.set(target, depsMap = new Map());
  }
  let deps = depsMap.get(key);
  if(!deps) {
    depsMap.set(key, (deps = []));
  }
  deps.push(activeEffect);
}

// 触发修改属性的回调函数
const trigger = (target, key) => {
  const deps = targetMap?.get(target)?.get(key);
  deps && deps.forEach(dep => dep());
}

// 监听函数，当fn内用到的对象属性值发生变化时触发执行fn
const effect = (fn) => {
  try {
    effectStack.push(fn);
    fn(); // 首次执行收集依赖
  } finally {
    effectStack.pop();
  }
}


// 测试
let obj = reactive({ a: 1, b: { c: 3 } });
effect(() => {
  console.log(obj.a);
  console.log(obj.b.c);
  console.log('----------');
});
setInterval(() => {
  obj.a++;
  obj.b.c++;
}, 1000);